home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / hce.lha / HCE / HCESource / TOP / Source / peep2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  17.6 KB  |  837 lines

  1. /* Copyright (c) 1988,1991 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * 2-instruction peephole optimizations
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. /*
  20.  * ipeep2(bp, i1) - look for 2-instruction optimizations at the given inst.
  21.  */
  22. static    bool
  23. ipeep2(bp, i1)
  24. BLOCK    *bp;
  25. register INST    *i1;
  26. {
  27.     register INST    *i2;        /* the next instruction */
  28.     register INST    *ti2;        /* "temporary" next inst */
  29.  
  30.     register int    op1, op2;    /* opcodes, for speed */
  31.     register int    sm1, dm1;    /* src, dst amode inst. 1 */
  32.     register int    dr1;        /* dest. reg. inst. 1 */
  33.  
  34.     i2  = i1->next;
  35.     op1 = i1->opcode;
  36.     op2 = i2->opcode;
  37.  
  38.     sm1 = i1->src.amode;
  39.     dm1 = i1->dst.amode;
  40.     dr1 = i1->dst.areg;
  41.  
  42.     /*
  43.      * Avoid stack fix-ups after a call if possible.
  44.      */
  45.  
  46.     if (gflag)                /* V2 */
  47.         goto skip_stack_stuff;        /* V2 */
  48.  
  49.     /*
  50.      *    addq    #4,sp
  51.      *    ... stuff that doesn't use SP ...
  52.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  53.      */
  54.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 4 &&
  55.         dm1 == REG && dr1 == SP) {
  56.  
  57.         ti2 = i2;
  58.         while (!uses(ti2, SP)) {
  59.             if (ti2->next == NULL)
  60.                 goto end2;
  61.             ti2 = ti2->next;
  62.         }
  63.  
  64.         if (ti2->opcode == MOVE && ti2->flags == LENL &&
  65.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  66.                 ti2->dst.amode = REGI;
  67.                 delinst(bp, i1);
  68.                 DBG(printf("%d ", __LINE__))
  69.                 return TRUE;
  70.         }
  71.     }
  72. end2:
  73.  
  74.     /*
  75.      *    addq    #2,sp
  76.      *    ... stuff that doesn't use SP ...
  77.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  78.      */
  79.     if (op1 == ADDQ && sm1 == IMM && i1->src.disp == 2 &&
  80.         dm1 == REG && dr1 == SP) {
  81.  
  82.         ti2 = i2;
  83.         while (!uses(ti2, SP)) {
  84.             if (ti2->next == NULL)
  85.                 goto end3;
  86.             ti2 = ti2->next;
  87.         }
  88.  
  89.         if (ti2->opcode == MOVE && ti2->flags == LENW &&
  90.             ti2->dst.amode == (REGI|DEC) && ti2->dst.areg == SP) {
  91.                 ti2->dst.amode = REGI;
  92.                 delinst(bp, i1);
  93.                 DBG(printf("%d ", __LINE__))
  94.                 return TRUE;
  95.         }
  96.     }
  97. end3:
  98.  
  99. skip_stack_stuff:    /* V2 */
  100.  
  101.     /*
  102.      * Avoid "tst" instructions following instructions that
  103.      * set the Z flag.
  104.      */
  105.  
  106.     /*
  107.      *    move.x    X, Y        =>    move.x    X, Y
  108.      *    tst.x    X or Y            ...deleted...
  109.      *    beq/bne                beq/bne
  110.      *
  111.      *    Where Y is not An, because "movea" doesn't set the
  112.      *    zero flag.
  113.      */
  114.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  115.         op1 == MOVE && op2 == TST &&
  116.         i1->flags == i2->flags) {
  117.  
  118.         /*
  119.          * If pre-decrement is set on the dest. of the move,
  120.          * don't let that screw up the operand comparison.
  121.          */
  122.         if (dm1 & DEC)
  123.             dm1 &= ~DEC;
  124.  
  125.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  126.             if (dm1 != REG || ISD(dr1)) {
  127.                     delinst(bp, i2);
  128.                     DBG(printf("%d ", __LINE__))
  129.                     return TRUE;
  130.             }
  131.         }
  132.     }
  133.  
  134.     /*
  135.      *    and.x    X, Y        =>    and.x    X, Y
  136.      *    tst.x    X or Y            ...deleted...
  137.      *    beq/bne                beq/bne
  138.      *
  139.      *    Where Y is not An, because "movea" doesn't set the
  140.      *    zero flag.
  141.      */
  142.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  143.         op1 == AND && op2 == TST &&
  144.         i1->flags == i2->flags) {
  145.  
  146.         /*
  147.          * If pre-decrement is set on the dest. of the move,
  148.          * don't let that screw up the operand comparison.
  149.          */
  150.         if (dm1 & DEC)
  151.             dm1 &= ~DEC;
  152.  
  153.         if (opeq(&i1->dst, &i2->src) || opeq(&i1->src, &i2->src)) {
  154.             if (dm1 != REG || ISD(dr1)) {
  155.                     delinst(bp, i2);
  156.                     DBG(printf("%d ", __LINE__))
  157.                     return TRUE;
  158.             }
  159.         }
  160.     }
  161.  
  162.     /*
  163.      *    ext.x    Dn        =>    ext.x    Dn
  164.      *    tst.x    Dn            ...deleted...
  165.      *    beq/bne                beq/bne
  166.      *
  167.      *    Where Y is not An, because "movea" doesn't set the
  168.      *    zero flag.
  169.      */
  170.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  171.         op1 == EXT && op2 == TST &&
  172.         i1->flags == i2->flags) {
  173.  
  174.         if (sm1 == REG && ISD(i1->src.areg) &&
  175.             i2->src.amode == REG && i1->src.areg == i2->src.areg) {
  176.                 delinst(bp, i2);
  177.                 DBG(printf("%d ", __LINE__))
  178.                 return TRUE;
  179.         }
  180.     }
  181.  
  182.     /*
  183.      *    move.?    X, Dn        =>    move.?    X, Dn
  184.      *    ext.?    Dn            ...deleted...
  185.      *    beq/bne                beq/bne
  186.      *
  187.      *    Where Dn is dead after the "ext".
  188.      */
  189.     if (bp->last == i2 && (bp->bcode == BEQ || bp->bcode == BNE) &&
  190.         op1 == MOVE && op2 == EXT) {
  191.  
  192.         if (dm1 == REG && ISD(dr1) &&
  193.             i2->src.amode == REG && dr1 == i2->src.areg) {
  194.             if ((i2->live & RM(i2->src.areg)) == 0) {
  195.                 delinst(bp, i2);
  196.                     DBG(printf("%d ", __LINE__))
  197.                  return TRUE;
  198.             }
  199.         }
  200.     }
  201.  
  202.     /*
  203.      *    ext.l    Dm        =>    ...deleted...
  204.      *    tst.l    Dm            tst.w    Dm
  205.      *
  206.      *    where Dm is dead after the "tst".
  207.      */
  208.     if (op1 == EXT && op2 == TST &&
  209.         ((i1->flags & LENL) != 0) &&  ((i2->flags & LENL) != 0) &&
  210.         (i1->src.areg == i2->src.areg) && ISD(i1->src.areg)) {
  211.  
  212.         if ((i2->live & RM(i2->src.areg)) == 0) {
  213.             i2->flags = LENW;
  214.             delinst(bp, i1);
  215.                 DBG(printf("%d ", __LINE__))
  216.             return TRUE;
  217.         }
  218.     }
  219.  
  220.     /*
  221.      *    ext.l    Dm        =>    ...deleted...
  222.      *    ???    N(An,Dm.l), ??        ???    N(An,Dm.w), ??
  223.      *
  224.      *    Where Dm is dead
  225.      */
  226.     if ((op1 == EXT) && (i1->flags & LENL) &&
  227.         (i2->src.amode == (REGIDX|XLONG)) &&
  228.         (i1->src.areg == i2->src.ireg)) {
  229.  
  230.         if ((i2->live & RM(i1->src.areg)) == 0) {
  231.             i2->src.amode &= ~XLONG;
  232.             delinst(bp, i1);
  233.                 DBG(printf("%d ", __LINE__))
  234.             return TRUE;
  235.         }
  236.     }
  237.  
  238.     /*
  239.      *    ext.l    Dm        =>    ...deleted...
  240.      *    ???    ??, N(An,Dm.l)        ???    ??, N(An,Dm.w)
  241.      *
  242.      *    Where Dm is dead
  243.      */
  244.     if ((op1 == EXT) && (i1->flags & LENL) &&
  245.         (i2->dst.amode == (REGIDX|XLONG)) &&
  246.         (i1->src.areg == i2->dst.ireg)) {
  247.  
  248.         if ((i2->live & RM(i1->src.areg)) == 0) {
  249.             i2->dst.amode &= ~XLONG;
  250.             delinst(bp, i1);
  251.                 DBG(printf("%d ", __LINE__))
  252.             return TRUE;
  253.         }
  254.     }
  255.  
  256.     /*
  257.      * Avoid intermediate registers.
  258.      */
  259.  
  260.     /*
  261.      *    move.x    X, Dm        =>    INST.x    X, Dn
  262.      *    INST.x    Dm, Dn
  263.      *
  264.      *    where Dm is dead, and INST is one of: add, sub, and, or, cmp
  265.      */
  266.     if ((op1 == MOVE) &&
  267.         ((op2==ADD)||(op2==SUB)||(op2==AND)||(op2==OR)||(op2==CMP)) &&
  268.         (i1->flags == i2->flags) &&
  269.         (dm1 == REG) && ISD(dr1) &&
  270.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  271.         (dr1 == i2->src.areg) &&
  272.         (i2->dst.amode == REG) && ISD(i2->dst.areg)) {
  273.  
  274.         if ((i2->live & RM(i2->src.areg)) == 0) {
  275.  
  276.             i1->opcode = i2->opcode;
  277.             i1->dst.areg = i2->dst.areg;
  278.  
  279.             delinst(bp, i2);
  280.                 DBG(printf("%d ", __LINE__))
  281.             return TRUE;
  282.         }
  283.     }
  284.  
  285.     /*
  286.      * Silly moves
  287.      */
  288.  
  289.     /*
  290.      *    move.x    X, Y        =>    move.x    X, Y
  291.      *    move.x    Y, X
  292.      */
  293.     if ((op1 == MOVE) && (op2 == MOVE) &&
  294.         (i1->flags == i2->flags) &&
  295.         opeq(&i1->src, &i2->dst) && opeq(&i1->dst, &i2->src) &&
  296.         ((i1->src.amode & (INC|DEC)) == 0) &&
  297.         ((i1->dst.amode & (INC|DEC)) == 0)) {
  298.  
  299.              delinst(bp, i2);
  300.             DBG(printf("%d ", __LINE__))
  301.              return TRUE;
  302.     }
  303.  
  304.     /*
  305.      *    move.x    X, Y        =>    move.x    X, Rn
  306.      *    move.x    Y, Rn            move.x    Rn, Y
  307.      *
  308.      *    where Y isn't INC or DEC, and isn't register direct
  309.      *    and Y doesn't depend on Rn
  310.      */
  311.     if ((op1 == MOVE) && (op2 == MOVE) && (i2->dst.amode == REG) &&
  312.         opeq(&i1->dst, &i2->src) && ((i1->dst.amode & (INC|DEC)) == 0) &&
  313.         (i1->flags == i2->flags) && (i1->dst.amode != REG) &&
  314.         !uses(i1, i2->dst.areg)) {
  315.  
  316.         freeop(&i1->dst);
  317.         i1->dst = i2->dst;
  318.         i2->dst = i2->src;
  319.         i2->src = i1->dst;
  320.  
  321.         DBG(printf("%d ", __LINE__))
  322.         return TRUE;
  323.     }
  324.  
  325.  
  326.     /*
  327.      *    move.x    Dm, X        =>    move.x    Dm, X
  328.      *    move.x    X, Y            move.x    Dm, Y
  329.      *
  330.      * Where 'x' is the same, and 'X' has no side-effects.
  331.      */
  332.     if ((op1 == MOVE) && (op2 == MOVE) &&
  333.         (sm1 == REG) && ISD(i1->src.areg) &&
  334.         (i1->flags == i2->flags) && opeq(&i1->dst, &i2->src) &&
  335.         ((dm1 & (DEC|INC)) == 0)) {
  336.  
  337.         freeop(&i2->src);
  338.         i2->src = i1->src;
  339.            DBG(printf("%d ", __LINE__))
  340.             return TRUE;
  341.     }
  342.  
  343.     /*
  344.      *    move.?    Rm, Rn        =>    move.?    Rm, Rn
  345.      *    ... stuff ...            ... stuff ...
  346.      *    move.?    Rm, Rn
  347.      *
  348.      *    where "stuff" doesn't set Rm or Rn. Also make sure that
  349.      *    the second move isn't followed by a conditional branch.
  350.      *    In that case leave everything alone since the branch
  351.      *    probably relies on flags set by the move.
  352.      */
  353.     if ((op1 == MOVE) && (sm1 == REG) && (dm1 == REG)) {
  354.         int    s1 = i1->src.areg;    /* source reg of inst. 1 */
  355.  
  356.         ti2 = i2;
  357.         while (ti2 != NULL && !sets(ti2, s1) && !sets(ti2, dr1)) {
  358.  
  359.             if ((ti2->opcode==MOVE) && (i1->flags==ti2->flags) &&
  360.                 (ti2->src.amode==REG) && (ti2->dst.amode==REG) &&
  361.                 (i1->src.areg == ti2->src.areg) &&
  362.                 (i1->dst.areg == ti2->dst.areg) &&
  363.                 ((bp->last != ti2) || (bp->bcond == NULL)) ) {
  364.  
  365.                      delinst(bp, ti2);
  366.                     DBG(printf("%d ", __LINE__))
  367.                      return TRUE;
  368.             }
  369.             ti2 = ti2->next;
  370.         }
  371.     }
  372.  
  373.     /*
  374.      *    move.l    Am, Dn        =>    move.l    Am, Ao
  375.      *    ... stuff ...            ... stuff ...
  376.      *    move.l    Dn, Ao
  377.      *
  378.      *    where "stuff" doesn't set Dn.
  379.      */
  380.     if ((op1 == MOVE) && (i1->flags == LENL) &&
  381.         (sm1 == REG) && ISA(i1->src.areg) &&
  382.         (dm1 == REG) && ISD(dr1)) {
  383.  
  384.         ti2 = i2;
  385.         while (!sets(ti2, dr1)) {
  386.  
  387.             if ((ti2->opcode == MOVE) && (ti2->flags == LENL) &&
  388.                 (ti2->src.amode == REG) && ISD(ti2->src.areg) &&
  389.                 (ti2->dst.amode == REG) && ISA(ti2->dst.areg) &&
  390.                 (dr1 == ti2->src.areg)) {
  391.  
  392.                 /*
  393.                  * If the intermediate register isn't dead,
  394.                  * then we have to keep using it.
  395.                  */
  396.                 if ((ti2->live & RM(ti2->src.areg)) != 0)
  397.                     goto end14;
  398.  
  399.                 i1->dst.areg = ti2->dst.areg;
  400.  
  401.                      delinst(bp, ti2);
  402.                     DBG(printf("%d ", __LINE__))
  403.                      return TRUE;
  404.             }
  405.  
  406.             if (ti2->next == NULL)
  407.                 goto end14;
  408.  
  409.             ti2 = ti2->next;
  410.         }
  411.     }
  412. end14:
  413.  
  414.     /*
  415.      *    move.l    Dm, An        =>    move.l    Dm, Ao
  416.      *    lea    (An), Ao
  417.      *
  418.      *    where An is dead
  419.      */
  420.     if ((op1 == MOVE) && (op2 == LEA) &&
  421.         (sm1 == REG) && ISD(i1->src.areg) &&
  422.         (dm1 == REG) && ISA(dr1) &&
  423.         (i2->src.amode == REGI) && (i2->dst.amode == REG) &&
  424.         ISA(i2->dst.areg) && (dr1 == i2->src.areg)) {
  425.  
  426.         if ((i2->live & RM(i2->src.areg)) == 0) {
  427.  
  428.             i1->dst.areg = i2->dst.areg;
  429.  
  430.             delinst(bp, i2);
  431.                 DBG(printf("%d ", __LINE__))
  432.             return TRUE;
  433.         }
  434.     }
  435.  
  436.     /*
  437.      *    lea    X, An        =>    lea    X, Ao
  438.      *    lea    (An), Ao
  439.      *
  440.      *    where An is dead
  441.      */
  442.     if ((op1 == LEA) && (op2 == LEA) &&
  443.         (i2->src.amode == REGI) && (dr1 == i2->src.areg)) {
  444.  
  445.         if ((i2->live & RM(i2->src.areg)) == 0) {
  446.  
  447.             i1->dst.areg = i2->dst.areg;
  448.  
  449.             delinst(bp, i2);
  450.                 DBG(printf("%d ", __LINE__))
  451.             return TRUE;
  452.         }
  453.     }
  454.  
  455.     /*
  456.      *    lea    N(Am), Am    =>
  457.      *    ?    (Am)[,...]        ?    N(Am)[,...]
  458.      *
  459.      *    Where Am is either dead after the second instruction or
  460.      *    is a direct destination of the second instruction.
  461.      */
  462.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  463.         (i1->src.areg == i1->dst.areg) &&
  464.         (i2->src.amode == REGI) && (i1->dst.areg == i2->src.areg)) {
  465.  
  466.         if (((i2->live & RM(i2->src.areg)) == 0) ||
  467.            ((i2->dst.amode == REG) && (i2->dst.areg == i2->src.areg))) {
  468.             i2->src.amode = REGID;
  469.             i2->src.disp = i1->src.disp;
  470.             delinst(bp, i1);
  471.                 DBG(printf("%d ", __LINE__))
  472.             return TRUE;
  473.         }
  474.     }
  475.  
  476.     /*
  477.      *    lea    N(Am), Am    =>
  478.      *    ?    X, (Am)            ?    X, N(Am)
  479.      *
  480.      *    Where X doesn't reference Am, and Am is dead after the
  481.      *    second instruction.
  482.      */
  483.     if ((op1 == LEA) && (i1->src.amode == REGID) &&
  484.         (i1->src.areg == i1->dst.areg) &&
  485.         (i2->dst.amode == REGI) && (i1->dst.areg == i2->dst.areg)) {
  486.  
  487.         if (((i2->live & RM(i2->dst.areg)) == 0) &&
  488.             ((i2->src.amode == IMM) || (i2->src.amode == ABS) ||
  489.              (i2->src.areg != i2->dst.areg))) {
  490.             i2->dst.amode = REGID;
  491.             i2->dst.disp = i1->src.disp;
  492.             delinst(bp, i1);
  493.                 DBG(printf("%d ", __LINE__))
  494.             return TRUE;
  495.         }
  496.     }
  497.  
  498.     /*
  499.      *    lea    X, Am        =>    ...deleted...
  500.      *    clr.x    (Am)            clr.x    X
  501.      *
  502.      *    where Am is dead
  503.      */
  504.     if ((op1 == LEA) && (op2 == CLR) && i2->src.amode == REGI &&
  505.         (i1->dst.areg == i2->src.areg)) {
  506.  
  507.         if ((i2->live & RM(i2->src.areg)) == 0) {
  508.             i2->src = i1->src;
  509.  
  510.             delinst(bp, i1);
  511.                 DBG(printf("%d ", __LINE__))
  512.             return TRUE;
  513.         }
  514.     }
  515.  
  516.     /*
  517.      *    lea    X, Am        =>    ...deleted...
  518.      *    move.x    Y, (Am)            move.x    Y, X
  519.      *
  520.      *    where Am is dead
  521.      */
  522.     if ((op1 == LEA) && (op2 == MOVE) && i2->dst.amode == REGI &&
  523.         (i1->dst.areg == i2->dst.areg)) {
  524.  
  525.         if ((i2->live & RM(i2->dst.areg)) == 0) {
  526.             i2->dst = i1->src;
  527.  
  528.             delinst(bp, i1);
  529.                 DBG(printf("%d ", __LINE__))
  530.             return TRUE;
  531.         }
  532.     }
  533.  
  534.     /*
  535.      *    lea    X, Am        =>    ...deleted...
  536.      *    move.x    (Am), Y            move.x    X, Y
  537.      *
  538.      *    where Am is dead
  539.      */
  540.     if ((op1 == LEA) && (op2 == MOVE) && i2->src.amode == REGI &&
  541.         (i1->dst.areg == i2->src.areg)) {
  542.  
  543.         if ((i2->live & RM(i2->src.areg)) == 0) {
  544.             i2->src = i1->src;
  545.  
  546.             delinst(bp, i1);
  547.                 DBG(printf("%d ", __LINE__))
  548.             return TRUE;
  549.         }
  550.     }
  551.  
  552.     /*
  553.      *    move.x    Dm, X        =>    move.x    Dm, X
  554.      *    cmp.x    #N, X            cmp.x    #N, Dm
  555.      *
  556.      *    Where X isn't register direct.
  557.      *
  558.      *    Since X generally references memory, we can compare
  559.      *    with the register faster.
  560.      */
  561.     if ((op1 == MOVE) && (op2 == CMP) &&
  562.         (i1->flags == i2->flags) && (i2->src.amode == IMM) &&
  563.         (sm1 == REG) && ISD(i1->src.areg) && (dm1 != REG) &&
  564.         opeq(&i1->dst, &i2->dst) && ((dm1 & (INC|DEC)) == 0)) {
  565.  
  566.         freeop(&i2->dst);
  567.         i2->dst.amode = REG;
  568.         i2->dst.areg = i1->src.areg;
  569.  
  570.             DBG(printf("%d ", __LINE__))
  571.         return TRUE;
  572.     }
  573.  
  574.  
  575.     /*
  576.      * Try to use register indirect w/ displacement and/or index
  577.      */
  578.  
  579.     /*
  580.      *    add.l    Am, Dn        =>    lea    0(Am,Dn.l), Ao
  581.      *    move.l    Dn, Ao
  582.      *
  583.      *    where Dn is dead
  584.      */
  585.     if ((op1 == ADD) && (op2 == MOVE) &&
  586.         (sm1 == REG) && ISA(i1->src.areg) &&
  587.         (dm1 == REG) && ISD(dr1) &&
  588.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  589.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  590.         (dr1 == i2->src.areg) &&
  591.         (i1->flags & LENL) && (i2->flags & LENL)) {
  592.  
  593.         if ((i2->live & RM(i2->src.areg)) == 0) {
  594.  
  595.             i2->opcode = LEA;
  596.             i2->flags = 0;
  597.  
  598.             i2->src.amode = REGIDX|XLONG;
  599.             i2->src.disp = 0;
  600.             i2->src.areg = i1->src.areg;
  601.             i2->src.ireg = dr1;
  602.  
  603.                 delinst(bp, i1);
  604.                 DBG(printf("%d ", __LINE__))
  605.                 return TRUE;
  606.         }
  607.     }
  608.  
  609.     /*
  610.      *    add.l    Dm, An        =>    move.x    0(An,Dm.l), Do
  611.      *    move.x    (An), Do
  612.      *
  613.      *    where An is dead
  614.      */
  615.     if ((op1 == ADD) && (op2 == MOVE) &&
  616.         (sm1 == REG) && ISD(i1->src.areg) &&
  617.         (dm1 == REG) && ISA(dr1) &&
  618.         (i2->src.amode == REGI)&& ISA(i2->src.areg) &&
  619.         (i2->dst.amode == REG) && ISD(i2->dst.areg) &&
  620.         (dr1 == i2->src.areg) && (i1->flags & LENL)) {
  621.  
  622.         if ((i2->live & RM(i2->src.areg)) == 0) {
  623.  
  624.             i2->src.amode = REGIDX|XLONG;
  625.             i2->src.disp = 0;
  626.             i2->src.ireg = i1->src.areg;
  627.  
  628.                 delinst(bp, i1);
  629.                 DBG(printf("%d ", __LINE__))
  630.                 return TRUE;
  631.         }
  632.     }
  633.  
  634.     /*
  635.      *    lea    N(Am), An    =>    lea    N(Am,Do.l), An
  636.      *    add.l    Do, An
  637.      *
  638.      */
  639.     if ((op1 == LEA) && (op2 == ADD) &&
  640.         (sm1 == REGID) &&
  641.         (i2->src.amode == REG) && ISD(i2->src.areg) &&
  642.         (i2->dst.amode == REG) && ISA(i2->dst.areg) &&
  643.         (dr1 == i2->dst.areg) && D8OK(i1->src.disp)) {
  644.  
  645.         i1->src.amode = REGIDX|XLONG;
  646.         i1->src.ireg = i2->src.areg;
  647.         delinst(bp, i2);
  648.             DBG(printf("%d ", __LINE__))
  649.         return TRUE;
  650.     }
  651.  
  652.  
  653.  
  654.     /*
  655.      * Try to use the pre-decrement and post-increment modes
  656.      * whenever possible.
  657.      */
  658.  
  659.     /*
  660.      *    sub.l    #1, Am
  661.      *    ... stuff ...
  662.      *    ???.b    ..(Am)..    =>    ???.b    ..-(Am)..
  663.      *
  664.      *    Nothing in "stuff" can refer to Am.
  665.      */
  666.     if ((op1 == SUB) && (i1->flags & LENL) &&
  667.         (sm1 == IMM) && (i1->src.disp == 1) &&
  668.         (dm1 == REG) && ISA(dr1)) {
  669.  
  670.         while (i2 != NULL) {
  671.  
  672.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  673.  
  674.                 if ((i2->flags & LENB) == 0)
  675.                     goto end24;
  676.  
  677.                 i2->src.amode |= DEC;
  678.  
  679.                     delinst(bp, i1);
  680.                     DBG(printf("%d ", __LINE__))
  681.                     return TRUE;
  682.             }
  683.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  684.  
  685.                 if ((i2->flags & LENB) == 0)
  686.                     goto end24;
  687.  
  688.                 i2->dst.amode |= DEC;
  689.  
  690.                     delinst(bp, i1);
  691.                     DBG(printf("%d ", __LINE__))
  692.                     return TRUE;
  693.             }
  694.  
  695.             if (uses(i2, dr1))
  696.                 goto end24;
  697.  
  698.             if (i2->next == NULL)
  699.                 goto end24;
  700.             else
  701.                 i2 = i2->next;
  702.  
  703.         }
  704.     }
  705. end24:
  706.  
  707.     /*
  708.      *    sub.l    #2, Am
  709.      *    ... stuff ...
  710.      *    ???.w    ..(Am)..    =>    ???.w    ..-(Am)..
  711.      *
  712.      *    Nothing in "stuff" can refer to Am.
  713.      */
  714.     if ((op1 == SUB) && (i1->flags & LENL) &&
  715.         (sm1 == IMM) && (i1->src.disp == 2) &&
  716.         (dm1 == REG) && ISA(dr1)) {
  717.  
  718.         while (i2 != NULL) {
  719.  
  720.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  721.  
  722.                 if ((i2->flags & LENW) == 0)
  723.                     goto end26;
  724.  
  725.                 i2->src.amode |= DEC;
  726.  
  727.                     delinst(bp, i1);
  728.                     DBG(printf("%d ", __LINE__))
  729.                     return TRUE;
  730.             }
  731.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  732.  
  733.                 if ((i2->flags & LENW) == 0)
  734.                     goto end26;
  735.  
  736.                 i2->dst.amode |= DEC;
  737.  
  738.                     delinst(bp, i1);
  739.                     DBG(printf("%d ", __LINE__))
  740.                     return TRUE;
  741.             }
  742.  
  743.             if (uses(i2, dr1))
  744.                 goto end26;
  745.  
  746.             if (i2->next == NULL)
  747.                 goto end26;
  748.             else
  749.                 i2 = i2->next;
  750.  
  751.         }
  752.     }
  753. end26:
  754.  
  755.     /*
  756.      *    sub.l    #4, Am
  757.      *    ... stuff ...
  758.      *    ???.l    ..(Am)..    =>    ???.l    ..-(Am)..
  759.      *
  760.      *    Nothing in "stuff" can refer to Am.
  761.      */
  762.     if ((op1 == SUB) && (i1->flags & LENL) &&
  763.         (sm1 == IMM) && (i1->src.disp == 4) &&
  764.         (dm1 == REG) && ISA(dr1)) {
  765.  
  766.         while (i2 != NULL) {
  767.  
  768.             if (i2->src.amode == REGI && i2->src.areg == dr1) {
  769.  
  770.                 if ((i2->flags & LENL) == 0)
  771.                     goto end28;
  772.  
  773.                 i2->src.amode |= DEC;
  774.  
  775.                     delinst(bp, i1);
  776.                     DBG(printf("%d ", __LINE__))
  777.                     return TRUE;
  778.             }
  779.             if (i2->dst.amode == REGI && i2->dst.areg == dr1) {
  780.  
  781.                 if ((i2->flags & LENL) == 0)
  782.                     goto end28;
  783.  
  784.                 i2->dst.amode |= DEC;
  785.  
  786.                     delinst(bp, i1);
  787.                     DBG(printf("%d ", __LINE__))
  788.                     return TRUE;
  789.             }
  790.  
  791.             if (uses(i2, dr1))
  792.                 goto end28;
  793.  
  794.             if (i2->next == NULL)
  795.                 goto end28;
  796.             else
  797.                 i2 = i2->next;
  798.  
  799.         }
  800.     }
  801. end28:
  802.  
  803.     return FALSE;
  804. }
  805.  
  806. /*
  807.  * peep2(bp) - scan blocks starting at 'bp'
  808.  */
  809. bool
  810. peep2(bp)
  811. register BLOCK    *bp;
  812. {
  813.     register INST    *ip;
  814.     register bool    changed = FALSE;
  815.  
  816.     DBG(printf("p2 :"))
  817.  
  818.     for (; bp != NULL ;bp = bp->next) {
  819.         for (ip = bp->first; ip != NULL && ip->next != NULL ;) {
  820.             if (ipeep2(bp, ip)) {
  821.                 changed = TRUE;
  822.                 s_peep2++;
  823.                 bprep(bp);
  824.                 /*
  825.                  * If we had a match, then either instruction
  826.                  * may have been deleted, so the safe thing to
  827.                  * do is to go to the next block.
  828.                  */
  829.                 break;
  830.             } else
  831.                 ip = ip->next;
  832.         }
  833.     }
  834.     DBG(printf("\n"); fflush(stdout))
  835.     return changed;
  836. }
  837.